package com.alibaba.citrus.cr.unified.inventory.facade.service;

import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.unified.inventory.functions.consignmentOrder.ConsignmentOrderEntity;
import com.alibaba.citrus.cr.unified.inventory.functions.consignmentOrder.ConsignmentOrderFactory;
import com.alibaba.citrus.cr.unified.inventory.repository.ConsignmentOrderLineRepository;
import com.alibaba.citrus.cr.unified.inventory.repository.ConsignmentOrderRepository;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crunifiedinventory.api.consignmentorderwrite.dto.DeleteRequest;
import com.epoch.app.crunifiedinventory.api.consignmentorderwrite.service.ConsignmentOrderWriteService;
import com.epoch.app.crunifiedinventory.dto.request.ConsignmentOrderUpdateRequest;
import com.epoch.app.crunifiedinventory.dto.request.ConsignmentOrderWriteCreateRequest;
import com.epoch.app.crunifiedinventory.model.dto.ConsignmentOrderCreateResponse;
import com.epoch.app.crunifiedinventory.model.dto.ConsignmentOrderLineUpdateReq;
import com.epoch.app.crunifiedinventory.model.dto.ConsignmentOrderWriteUpdateRequest;
import com.epoch.app.crunifiedinventory.sdo.ConsignmentOrderLineSDO;
import com.epoch.app.crunifiedinventory.sdo.ConsignmentOrderSDO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Primary
public class ConsignmentOrderWriteServiceImpl implements ConsignmentOrderWriteService {

    private final Log log = Log.getLogger(ConsignmentOrderWriteServiceImpl.class);

    @Resource
    private ConsignmentOrderRepository consignmentOrderRepository;
    @Resource
    private ConsignmentOrderLineRepository consignmentOrderLineRepository;
    @Resource
    private EpochMessageService messageService;

    @Override
    @FacadeInvoker
    @Transactional(rollbackFor = Exception.class)
    public Result<ConsignmentOrderCreateResponse> create(ConsignmentOrderWriteCreateRequest consignmentOrderWriteCreateRequest) {

        ConsignmentOrderSDO query = consignmentOrderRepository.query(consignmentOrderWriteCreateRequest.getOuterDeliveryOrderId());
        if (query != null && Objects.equals(query.getStatus(),0)){
            log.error("ConsignmentOrderWriteServiceImpl_order_isDeleted:{}",JSON.toJSONString(consignmentOrderWriteCreateRequest));
            return Result.success(new ConsignmentOrderCreateResponse());
        }
        ConsignmentOrderEntity consignmentOrderEntity = new ConsignmentOrderEntity();
        if (query != null) {
            consignmentOrderRepository.deleteOrder(query);
            consignmentOrderEntity = ConsignmentOrderFactory.createConsignmentOrderCopy033Param(consignmentOrderWriteCreateRequest,query);
        }else{
            consignmentOrderEntity = ConsignmentOrderFactory.createConsignmentOrder(consignmentOrderWriteCreateRequest);
        }


        String s = consignmentOrderEntity.create();
        ConsignmentOrderCreateResponse response = new ConsignmentOrderCreateResponse();
        response.setId(s);
        //发送创建消息消息，订单接收
        try {
            messageService.sendMessage("consignment_order_message", "CR_CONSIGNMENT_V2", "ConsignmentCreated", consignmentOrderEntity.getConsignmentOrderSDO().getOuterDeliveryOrderId(), JSON.toJSONString(consignmentOrderEntity.getConsignmentOrderSDO()));
        } catch (Exception e) {
            //e.printStackTrace();
            log.info("发送交货单创建消息失败！",e);
        }

        try {
            messageService.sendMessage("consignment_order_message", "CR_CONSIGNMENT_V2", "updateOrderDeliveryQty", consignmentOrderEntity.getConsignmentOrderSDO().getOuterDeliveryOrderId(), JSON.toJSONString(consignmentOrderEntity.getConsignmentOrderSDO()));
        } catch (Exception e) {
            log.info("发送交货单消息更新订单交货数量消息失败！",e);
        }

        return Result.success(response);
    }

    @Override
    public Result<Boolean> deleteBySapDeliveryOrder(ConsignmentOrderWriteUpdateRequest consignmentOrderWriteUpdateRequest) {
        ConsignmentOrderSDO query = consignmentOrderRepository.query(consignmentOrderWriteUpdateRequest.getOuterDeliveryOrderId());
        if(query == null){
            log.info("consignmentOrder is not existed "+ consignmentOrderWriteUpdateRequest.getOuterDeliveryOrderId());
            return Result.success(true);
        }
        ConsignmentOrderEntity consignmentOrderEntity = ConsignmentOrderFactory.deleteConsignmentOrder(query);
        consignmentOrderEntity.delete();
        //发送删除消息，订单接收
        try {
            messageService.sendMessage("consignment_order_message", "CR_CONSIGNMENT_V2", "ConsignmentDeleted", consignmentOrderEntity.getConsignmentOrderSDO().getId(), JSON.toJSONString(consignmentOrderEntity.getConsignmentOrderSDO()));
            log.info("send consignment delete message ,consignmentId = {}",consignmentOrderWriteUpdateRequest.getOuterDeliveryOrderId());
        } catch (Exception e) {
            log.error("send consignment delete message fail！",e);
        }

        try {
            messageService.sendMessage("consignment_order_message", "CR_CONSIGNMENT_V2", "updateOrderDeliveryQty", consignmentOrderEntity.getConsignmentOrderSDO().getOuterDeliveryOrderId(), JSON.toJSONString(consignmentOrderEntity.getConsignmentOrderSDO()));
            log.info("send consignment update order delivery qty message ,consignmentId = {}",consignmentOrderWriteUpdateRequest.getOuterDeliveryOrderId());
        } catch (Exception e) {
            log.info("send consignment update order delivery qty message fail！",e);
        }

        return Result.success(true);
    }

    /**
     * update
     */
    @Override
    public Result<Void> update(ConsignmentOrderUpdateRequest consignmentOrderUpdateRequest) {
        log.info("consignmentOrderUpdateRequest " + JSON.toJSONString(consignmentOrderUpdateRequest));
        /**
         * 查询主单
         * 更新主单
         * 删除明细
         * 更新明细
         * 新增明细
         */
        ConsignmentOrderSDO orderSDO = consignmentOrderRepository.query(consignmentOrderUpdateRequest.getOuterDeliveryOrderId());
        if(orderSDO == null){
            log.info("consignmentOrder is not existed "+ consignmentOrderUpdateRequest.getOuterDeliveryOrderId());
            return Result.fail("OTS-04-001-00-15-061","ConsignmentOrderSDO not exist");
        }
        try {

            ConsignmentOrderSDO updateSDO = new ConsignmentOrderSDO();
            BeanUtils.copyProperties(consignmentOrderUpdateRequest, updateSDO);
            updateSDO.setId(orderSDO.getId());
            log.info("start update updateSDO={}",JSON.toJSONString(updateSDO));
            consignmentOrderRepository.update(updateSDO);
            log.info("done update updateSDO");
            if(consignmentOrderUpdateRequest.getConsignmentOrderLineRequest()==null
                    || consignmentOrderUpdateRequest.getConsignmentOrderLineRequest().size() == 0 ){
                return Result.success(null);
            }
            log.info("orderSDO " + JSON.toJSONString(orderSDO));

            Map<String, ConsignmentOrderLineSDO> oldLineMap = orderSDO.getConsignmentOrderLineSDOS().stream()
                    .collect(Collectors.toMap(e -> e.getOuterOrderLineId(), e -> e));

            Map<String, ConsignmentOrderLineUpdateReq> newLineMap = consignmentOrderUpdateRequest.getConsignmentOrderLineRequest().stream()
                    .collect(Collectors.toMap(e -> e.getOuterOrderLineId(), e -> e));

            for (ConsignmentOrderLineUpdateReq lineUpdateReq : consignmentOrderUpdateRequest.getConsignmentOrderLineRequest()) {
                if (oldLineMap.containsKey(lineUpdateReq.getOuterOrderLineId())) {
                    log.info("start update updateLineSDO");
                    ConsignmentOrderLineSDO updateLineSDO = new ConsignmentOrderLineSDO();
                    BeanUtils.copyProperties(lineUpdateReq, updateLineSDO);
                    updateLineSDO.setId(oldLineMap.get(lineUpdateReq.getOuterOrderLineId()).getId());
                    updateLineSDO.setConsignmentOrderId(orderSDO.getId());
                    consignmentOrderLineRepository.update(updateLineSDO);
                    log.info("done update updateLineSDO");
                } else {
                    log.info("start create updateLineSDO");
                    ConsignmentOrderLineSDO insertLineSDO = new ConsignmentOrderLineSDO();
                    BeanUtils.copyProperties(lineUpdateReq, insertLineSDO);
                    insertLineSDO.setId(null);
                    insertLineSDO.setConsignmentOrderId(orderSDO.getId());
                    insertLineSDO.setStatus(1);
                    insertLineSDO.setSyncVersion(0);
                    consignmentOrderLineRepository.create(insertLineSDO);
                    log.info("done create insertLineSDO");
                }
            }

            for (ConsignmentOrderLineSDO lineSDO : orderSDO.getConsignmentOrderLineSDOS()) {
                if (!newLineMap.containsKey(lineSDO.getOuterOrderLineId())) {
                    log.info("start delete lineSDO");
                    lineSDO.setStatus(0);
                    consignmentOrderLineRepository.delete(lineSDO);
                    log.info("done delete lineSDO");
                }
            }
        }catch (Exception e){
            log.info("update deliveryOrder error " + e.getMessage() , e);
            e.printStackTrace();
        }
        return Result.success(null);
    }

    /**
     * createOrder
     */
    @Override
    public Result<Void> createOrder(ConsignmentOrderWriteCreateRequest consignmentOrderWriteCreateRequest) {

        ConsignmentOrderEntity consignmentOrderEntity = ConsignmentOrderFactory.createConsignmentOrder(consignmentOrderWriteCreateRequest);
        String s = consignmentOrderEntity.create();
        return Result.success(null);
    }

    /**
     * delete
     */
    @Override
    public Result<Void> delete(DeleteRequest deleteRequest) {
        ConsignmentOrderSDO query = consignmentOrderRepository.query(deleteRequest.getOrderId());
        if(query == null){
            log.info("consignmentOrder is not existed "+ deleteRequest.getOrderId());
            return Result.success(null);
        }
        ConsignmentOrderEntity consignmentOrderEntity = ConsignmentOrderFactory.deleteConsignmentOrder(query);
        consignmentOrderEntity.delete();
        return Result.success(null);
    }

    @Override
    public Result<Void> updateFor033(ConsignmentOrderUpdateRequest consignmentOrderUpdateRequest) {
        log.info("updateFor033 consignmentOrderUpdateRequest " + JSON.toJSONString(consignmentOrderUpdateRequest));

        ConsignmentOrderSDO orderSDO = consignmentOrderRepository.query(consignmentOrderUpdateRequest.getOuterDeliveryOrderId());
        if(orderSDO == null){
            log.info("updateFor033 consignmentOrder is not existed "+ consignmentOrderUpdateRequest.getOuterDeliveryOrderId());
            return Result.fail("OTS-04-001-00-15-061","ConsignmentOrderSDO not exist");
        }
        try {
            ConsignmentOrderSDO updateSDO = new ConsignmentOrderSDO();
            BeanUtils.copyProperties(consignmentOrderUpdateRequest, updateSDO);
            updateSDO.setId(orderSDO.getId());
            log.info("updateFor033 start update updateSDO={}",JSON.toJSONString(updateSDO));
            boolean result = consignmentOrderRepository.updateFor033(updateSDO);
            log.info("updateFor033 start update result={}",result);
            //如果更新失败了，重试
            if(!result){
                return Result.fail("OTS-04-001-00-15-061","ConsignmentOrderSDO update fail");
            }
            if(consignmentOrderUpdateRequest.getConsignmentOrderLineRequest()==null
                    || consignmentOrderUpdateRequest.getConsignmentOrderLineRequest().size() == 0 ){
                return Result.success(null);
            }
            log.info("updateFor033 orderSDO " + JSON.toJSONString(orderSDO));

            Map<String, ConsignmentOrderLineSDO> oldLineMap = orderSDO.getConsignmentOrderLineSDOS().stream()
                    .collect(Collectors.toMap(e -> e.getOuterOrderLineId(), e -> e));

            Map<String, ConsignmentOrderLineUpdateReq> newLineMap = consignmentOrderUpdateRequest.getConsignmentOrderLineRequest().stream()
                    .collect(Collectors.toMap(e -> e.getOuterOrderLineId(), e -> e));

            for (ConsignmentOrderLineUpdateReq lineUpdateReq : consignmentOrderUpdateRequest.getConsignmentOrderLineRequest()) {
                if (oldLineMap.containsKey(lineUpdateReq.getOuterOrderLineId())) {
                    log.info("updateFor033 start update updateLineSDO");
                    ConsignmentOrderLineSDO updateLineSDO = new ConsignmentOrderLineSDO();
                    BeanUtils.copyProperties(lineUpdateReq, updateLineSDO);
                    updateLineSDO.setId(oldLineMap.get(lineUpdateReq.getOuterOrderLineId()).getId());
                    updateLineSDO.setConsignmentOrderId(orderSDO.getId());
                    consignmentOrderLineRepository.update(updateLineSDO);
                    log.info("updateFor033 done update updateLineSDO");
                } else {
                    log.info("updateFor033 start create updateLineSDO");
                    ConsignmentOrderLineSDO insertLineSDO = new ConsignmentOrderLineSDO();
                    BeanUtils.copyProperties(lineUpdateReq, insertLineSDO);
                    insertLineSDO.setId(null);
                    insertLineSDO.setConsignmentOrderId(orderSDO.getId());
                    insertLineSDO.setStatus(1);
                    insertLineSDO.setSyncVersion(0);
                    consignmentOrderLineRepository.create(insertLineSDO);
                    log.info("updateFor033 done create insertLineSDO");
                }
            }

            for (ConsignmentOrderLineSDO lineSDO : orderSDO.getConsignmentOrderLineSDOS()) {
                if (!newLineMap.containsKey(lineSDO.getOuterOrderLineId())) {
                    log.info("updateFor033 start delete lineSDO");
                    lineSDO.setStatus(0);
                    consignmentOrderLineRepository.delete(lineSDO);
                    log.info("updateFor033 done delete lineSDO");
                }
            }
        }catch (Exception e){
            log.error("updateFor033 update deliveryOrder error " , e);
        }
        return Result.success(null);
    }
}
